#include "stdafx.h"
#include "MemoryPool.h"

CMemPool::CMemPool(size_t size, size_t growStep)
:m_allHead(NULL),
m_freeHead(NULL),
m_size(size),
m_growStep(growStep),
m_freeSize(0),
m_mallocCount(0)
{
	if(m_size < sizeof(void*)) m_size = sizeof(void*);
}

CMemPool::~CMemPool()
{
	while(m_allHead)
	{
		void* pBlock = m_allHead;
		m_allHead = (void*)*(uintptr_t*)(m_allHead);
		::free(pBlock);
	}
}

void* CMemPool::malloc()
{
	if(m_freeHead)
	{
		void* address = m_freeHead;
		m_freeHead = (void*)*(uintptr_t*)m_freeHead;
		--m_freeSize;
		return address;
	}
	else
	{
		void* rawMem = ::malloc(m_size * m_growStep + sizeof(void*));
		if(!rawMem) return NULL;
		++m_mallocCount;
		m_freeSize += m_growStep;
		*(uintptr_t*)rawMem = (uintptr_t)m_allHead;
		m_allHead = rawMem;
		m_freeHead = (char*)rawMem + sizeof(void*);
		for(size_t index = 0; index < m_growStep - 1; ++index)
			(*(uintptr_t*)((char*)m_freeHead + index * m_size)) = (uintptr_t)((char*)m_freeHead + (index + 1) * m_size);
		(*(uintptr_t*)((char*)m_freeHead + (m_growStep - 1) * m_size)) = NULL;
		return malloc();
	}

}

void CMemPool::free(void* address)
{
	if(!address) return;
	(*(uintptr_t*)address) = (uintptr_t)m_freeHead;
	m_freeHead = address;
	++m_freeSize;
}
